import mongoose from 'mongoose';
import { Department, IDepartment, IDepartmentDocument } from '../models/department';

/**
 * 部门数据访问对象
 * 提供部门相关的数据库操作方法
 */
export class DepartmentDAO {
  /**
   * 创建新部门
   * @param departmentData 部门数据
   * @returns 创建的部门文档
   */
  async create(departmentData: Partial<IDepartment>): Promise<IDepartmentDocument> {
    try {
      const department = new Department(departmentData);
      return await department.save();
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 根据ID查找部门
   * @param id 部门ID
   * @returns 部门文档或null
   */
  async findById(id: mongoose.Types.ObjectId | string): Promise<IDepartmentDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid department ID format');
      }
      return await Department.findById(id).exec();
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据团队ID查找部门
   * @param teamId 团队ID
   * @returns 部门文档数组
   */
  async findByTeam(teamId: mongoose.Types.ObjectId | string): Promise<IDepartmentDocument[]> {
    try {
      if (!mongoose.Types.ObjectId.isValid(teamId)) {
        throw new Error('Invalid team ID format');
      }
      return await Department.findByTeam(teamId as mongoose.Types.ObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新部门信息
   * @param id 部门ID
   * @param updateData 更新数据
   * @returns 更新后的部门文档或null
   */
  async update(
    id: mongoose.Types.ObjectId | string,
    updateData: Partial<IDepartment>
  ): Promise<IDepartmentDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid department ID format');
      }

      // 移除不应该被更新的字段
      const { _id, createdAt, ...safeUpdateData } = updateData as any;
      
      // 设置更新时间
      safeUpdateData.updatedAt = new Date();

      const updatedDepartment = await Department.findByIdAndUpdate(
        id,
        safeUpdateData,
        { 
          new: true, 
          runValidators: true,
          lean: false
        }
      ).exec();

      return updatedDepartment;
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 删除部门
   * @param id 部门ID
   * @returns 是否删除成功
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid department ID format');
      }

      const result = await Department.findByIdAndDelete(id).exec();
      return result !== null;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据部门名称查找部门
   * @param name 部门名称
   * @returns 部门文档或null
   */
  async findByName(name: string): Promise<IDepartmentDocument | null> {
    try {
      return await Department.findByName(name);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据经理ID查找部门
   * @param managerId 经理ID
   * @returns 部门文档数组
   */
  async findByManager(managerId: mongoose.Types.ObjectId | string): Promise<IDepartmentDocument[]> {
    try {
      if (!mongoose.Types.ObjectId.isValid(managerId)) {
        throw new Error('Invalid manager ID format');
      }
      return await Department.findByManager(managerId as mongoose.Types.ObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据状态查找部门
   * @param status 状态值
   * @returns 部门文档数组
   */
  async findByStatus(status: number): Promise<IDepartmentDocument[]> {
    try {
      return await Department.findByStatus(status);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取所有部门（支持分页和过滤）
   * @param criteria 查询条件
   * @param options 分页和排序选项
   * @returns 部门列表和分页信息
   */
  async findAll(
    criteria: {
      name?: string;
      teamId?: mongoose.Types.ObjectId | string;
      managerId?: mongoose.Types.ObjectId | string;
      status?: number;
    } = {},
    options: {
      page?: number;
      limit?: number;
      sort?: string;
      select?: string;
    } = {}
  ): Promise<{ departments: IDepartmentDocument[]; total: number; page: number; totalPages: number }> {
    try {
      const {
        page = 1,
        limit = 10,
        sort = '-createdAt',
        select = ''
      } = options;

      // 构建查询条件
      const query: any = {};
      
      if (criteria.name) {
        query.name = { $regex: criteria.name, $options: 'i' };
      }
      
      if (criteria.teamId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.teamId)) {
          throw new Error('Invalid team ID format');
        }
        query.teamId = criteria.teamId;
      }
      
      if (criteria.managerId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.managerId)) {
          throw new Error('Invalid manager ID format');
        }
        query.managerId = criteria.managerId;
      }
      
      if (criteria.status !== undefined) {
        query.status = criteria.status;
      }

      // 计算跳过的文档数
      const skip = (page - 1) * limit;

      // 执行查询
      const [departments, total] = await Promise.all([
        Department.find(query)
          .select(select)
          .sort(sort)
          .skip(skip)
          .limit(limit)
          .exec(),
        Department.countDocuments(query).exec()
      ]);

      // 计算总页数
      const totalPages = Math.ceil(total / limit);

      return {
        departments,
        total,
        page,
        totalPages
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量创建部门
   * @param departmentsData 部门数据数组
   * @returns 创建的部门文档数组
   */
  async batchCreate(departmentsData: Partial<IDepartment>[]): Promise<IDepartmentDocument[]> {
    try {
      if (!Array.isArray(departmentsData) || departmentsData.length === 0) {
        throw new Error('Invalid departments data');
      }

      const departments = await Department.insertMany(departmentsData, {
        ordered: false, // 即使某个文档插入失败，也继续插入其他文档
        rawResult: false
      });

      return departments;
    } catch (error: any) {
      if (error.code === 11000) {
        throw new Error('Some departments already exist');
      }
      throw error;
    }
  }

  /**
   * 更新部门状态
   * @param id 部门ID
   * @param status 新状态
   * @returns 更新后的部门文档或null
   */
  async updateStatus(
    id: mongoose.Types.ObjectId | string,
    status: number
  ): Promise<IDepartmentDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid department ID format');
      }

      if (![0, 1].includes(status)) {
        throw new Error('Invalid status value');
      }

      const updatedDepartment = await Department.findByIdAndUpdate(
        id,
        { 
          status,
          updatedAt: new Date()
        },
        { 
          new: true, 
          runValidators: true,
          lean: false
        }
      ).exec();

      return updatedDepartment;
    } catch (error) {
      throw error;
    }
  }
}

export default DepartmentDAO;